package com.rpa.secure.servicerpasecure.interceptor;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rpa.secure.servicerpasecure.common.constant.JwtClaimsConstant;
import com.rpa.secure.servicerpasecure.common.constant.MessageConstant;
import com.rpa.secure.servicerpasecure.common.properties.JwtProperties;
import com.rpa.secure.servicerpasecure.common.result.Result;
import com.rpa.secure.servicerpasecure.common.util.CurrentTeacherInfoUtil;
import com.rpa.secure.servicerpasecure.common.util.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.web.util.ContentCachingRequestWrapper;


import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class JwtTokenInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 对访问接口的请求进行拦截，防止越权
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        RequestWrapper requestWrapper = new RequestWrapper(request);
        String requestBody = requestWrapper.getBody();
        Map<String, Object> params = new HashMap<>();

        // 校验 JWT
        String token = request.getHeader(jwtProperties.getTokenName());
        try {
            Claims claims = JwtUtil.parseJWT(jwtProperties.getSecretKey(), token);
            String teacherId = claims.get(JwtClaimsConstant.TEACHER_ID).toString();
            CurrentTeacherInfoUtil.setCurrentTeacherId(teacherId);
        } catch (Exception e) {
            response.setStatus(MessageConstant.IDEA_ID_IS_NULL);
            log.error("JWT 校验失败: " + e);
            return false;
        }

        // 解析请求体
        if (requestBody != null && !requestBody.isEmpty()) {
            try {
                // 尝试解析请求体为单个对象
                Map<String, Object> requestBodyMap = parseJsonToMap(requestBody);
                params.putAll(requestBodyMap);

                // 校验单个对象的 accountId 是否与 teacherId 匹配
                String courseId = MapUtil.getStr(params, "accountId", "");
                if (StrUtil.isEmpty(courseId) || !StrUtil.equals(courseId, CurrentTeacherInfoUtil.getCurrentTeacherId())) {
                    Result<Object> result = Result.error(MessageConstant.ULTRA_VIRES);
                    writeResponse(response, result);
                    return false;
                }
            } catch (IOException e) {
                // 如果解析为对象失败，再判断是否为数组
                if (requestBody.startsWith("[") && requestBody.endsWith("]")) {
                    // 请求体是 JSON 数组，解析为 List
                    List<Map<String, String>> requestBodyList = parseJsonToList(requestBody);
                    for (Map<String, String> item : requestBodyList) {
                        String courseId = MapUtil.getStr(item, "accountId", "");
                        // 校验每一条数据的 accountId 是否与 teacherId 匹配
                        if (StrUtil.isEmpty(courseId) || !courseId.equals(CurrentTeacherInfoUtil.getCurrentTeacherId())) {
                            Result<Object> result = Result.error(MessageConstant.ULTRA_VIRES);
                            writeResponse(response, result);
                            return false;
                        }
                    }
                } else {
                    // 如果既不是对象也不是数组，返回失败
                    Result<Object> result = Result.error("Invalid data format");
                    writeResponse(response, result);
                    return false;
                }
            }
        }

        return true;
    }

    private List<Map<String, String>> parseJsonToList(String json) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(json, new TypeReference<List<Map<String, String>>>() {});
        } catch (IOException e) {
            log.error("解析 JSON 数组失败", e);
            return new ArrayList<>();
        }
    }

    private Map<String, Object> parseJsonToMap(String json) throws IOException {
        // 使用 Jackson 解析 JSON 字符串为 Map
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 动态解析 JSON 中的字段，根据需要将字段解析为 List 或 String
            return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
        } catch (IOException e) {
            log.error("解析 JSON 失败", e);
            throw new IOException("解析 JSON 失败");
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        CurrentTeacherInfoUtil.remove();
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    private void writeResponse(ServletResponse response, Result result) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.print(JSONObject.toJSONString(result));
        writer.close();
        writer.flush();
    }

/*    private Map<String, String> parseJsonToMap(String json) {
        // 使用 Jackson 或 Gson 解析 JSON 字符串为 Map
        // 这里以 Jackson 为例
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(json, new TypeReference<Map<String, String>>() {
            });
        } catch (IOException e) {
            log.error("解析 JSON 失败", e);
            return new HashMap<>();
        }
    }*/

}
